Health Service Modelling Associates Programme Lambda
Entities are often the service users in your model.
Like buses, you might have none arrive for ages, then several at once.
We might have multiple generators for different kinds of patients, if they arrive at different rates.
Example of patients arriving via ambulance and via walk-in, with clearly different arrival rates
Example of multi-step mostly linear pathway, with patients having the possibility of leaving at multiple steps
Example of simple one-step resource use with a constrained resource
Here’s a sample of some code for a
import simpy
import random
import math
import matplotlib.pyplot as plt
import argparse
# --------------------------
# Parse command-line arguments
# --------------------------
parser = argparse.ArgumentParser(description="Healthcare Waiting List Simulation")
parser.add_argument("--patients", type=int, default=25, help="Average new patients per week (default: 25)")
parser.add_argument("--clinicians", type=int, default=4, help="Number of clinicians (default: 4)")
parser.add_argument("--patients_per_clinician_per_week", type=int, default=5, help="Patients each clinician can see per week (default: 5)")
parser.add_argument("--duration_years", type=int, default=3, help="Simulation duration in years (default: 3)")
parser.add_argument("--initial_waitlist", type=int, default=0, help="Initial waiting list length (default: 0)")
args = parser.parse_args()
# --------------------------
# Assign from arguments
# --------------------------
patients = args.patients
clinicians = args.clinicians
patients_per_clinician_per_week = args.patients_per_clinician_per_week
sim_duration_years = args.duration_years
waiting_list_start_length = args.initial_waitlist
# --------------------------
# Tracking variables
# --------------------------
waiting_times = []
queue_lengths = []
time_points = []
patients_seen = []
all_patients = []
random.seed(42)
# --------------------------
# Simulation functions
# --------------------------
def patient(env, name, nurses, arrival_time):
service_time = 1 / patients_per_clinician_per_week
patient_record = {
'name': name,
'arrival_time': arrival_time,
'service_start': None,
'wait_time_weeks': None,
'status': 'waiting'
}
all_patients.append(patient_record)
with nurses.request() as request:
yield request
wait_time = env.now - arrival_time
waiting_times.append(wait_time)
patient_record['service_start'] = env.now
patient_record['wait_time_weeks'] = wait_time
patient_record['status'] = 'seen'
patients_seen.append(patient_record.copy())
yield env.timeout(service_time)
def patient_generator(env, nurses):
for i in range(waiting_list_start_length):
env.process(patient(env, f"Initial Patient {i+1}", nurses, 0))
while True:
num_arrivals = math.ceil(random.normalvariate(patients, patients * 0.2))
num_arrivals = max(0, num_arrivals)
for i in range(num_arrivals):
env.process(patient(env, f"Week {math.ceil(env.now)} Patient {i+1}", nurses, env.now))
yield env.timeout(1)
def monitor_queue(env, nurses):
while True:
queue_lengths.append(len(nurses.queue))
time_points.append(env.now)
yield env.timeout(1)
# --------------------------
# Run simulation
# --------------------------
env = simpy.Environment()
nurses_resource = simpy.Resource(env, capacity=clinicians)
env.process(patient_generator(env, nurses_resource))
env.process(monitor_queue(env, nurses_resource))
env.run(until=sim_duration_years * 52)
# --------------------------
# Plot results
# --------------------------
plt.figure(figsize=(10, 4))
plt.plot(time_points, queue_lengths, linewidth=2, color='#1f77b4')
plt.xlabel('Time (weeks)')
plt.ylabel('Waiting List Length')
plt.title('Waiting List Length Over Time')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# --------------------------
# Print summary
# --------------------------
final_waiting_list = len(nurses_resource.queue)
patients_seen_count = len(patients_seen)
avg_wait = sum(waiting_times) / len(waiting_times) if waiting_times else 0
print("\n--- Simulation Summary ---")
print(f"Final Waiting List: {final_waiting_list}")
print(f"Patients Seen: {patients_seen_count}")
print(f"Average Wait (weeks): {avg_wait:.1f}")Run it from the terminal…

Free Python-based web app framework
App users don’t have to install Python
Hosting
Alternatives exit (Shiny, Dash)
Let’s return to our sample web app.
We’ll add
Are we seeing the full picture here?
Let’s make it clearer what the wait times mean.
A model is only as good as it’s spec.
What is the process - really?
I mean really really…
You’re setting the model up for failure if you don’t have the experts in the process in the room from the start
Even then, it can be complex to work out what to model and what to simplify (and the scenarios you want to test can really influence this)
And do you actually hold the data you need to parameterise the model?

What metrics/KPIs do you want to be able to measure?
How are you going to measure that the model reflects the current reality?
What do you need to be able to change?
Will the simplified model logic support the scenarios you want to test?
What do you need to be able to export?
Is this a one and done output, or an ongoing tool?
How do you assess that it made good predictions, and refine it?
How long does a model take?

Tip
In reality, a good model may take weeks to months - and may be iterated on for years
You’re now going to have a go with an interactive app.
In the app, you are running a hospital.
You usually have 24 rooms available, which are divided between
With 24 rooms, your system is coping.
Due to building work, you are temporarily going to have 20 rooms available.
You need to reallocate the number of rooms available to different steps of the pathway - but is it possible to keep the hospital running smoothly still?
Run the simulation with the default parameters
Change some parameters
What do you like about this app?
What would you want to change?
We’re going to take your model ideas from earlier and design a web app interface to go with them.
Text, metric cards, static plots, interactive plots, maps, downloadable reports
Could get them using something like draw.io or Excalidraw?
Choose a system to model from a couple of suggestions (choose some things that are quite simple), or do one of their own systems from their post-it notes earlier.